home *** CD-ROM | disk | FTP | other *** search
/ Ham Radio 2000 #1 / Ham Radio 2000.iso / ham2000 / tcp_ip / tnos / tnos100s / osk.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-11-14  |  25.2 KB  |  1,313 lines

  1. /* OS- and machine-dependent stuff for OS-9
  2.  * Copyright 1993 Brian A. Lantz, KO4KS
  3.  */
  4. #include <stdio.h>
  5. #include <conio.h>
  6. #include <dir.h>
  7. #include <dos.h>
  8. #include <io.h>
  9. #include <direct.h>
  10. #include <sys/stat.h>
  11. #include <string.h>
  12. #include <process.h>
  13. #include <fcntl.h>
  14. #include <alloc.h>
  15. #include <stdarg.h>
  16. #include <bios.h>
  17. #include "global.h"
  18. #include "config.h"
  19. #include "mbuf.h"
  20. #include "proc.h"
  21. #include "iface.h"
  22. #include "internet.h"
  23. #include "tty.h"
  24. #include "socket.h"
  25. #include "smtp.h"
  26. #include "cmdparse.h"
  27. #include "dirutil.h"
  28. #include "pc.h"
  29. #include <modes.h>
  30. #include "i8250.h"
  31. #include <sgstat.h>
  32. #include <time.h>
  33.  
  34. #define    CTLC    0x3
  35. #define    DEL    0x7f
  36.  
  37. static int kbchar __ARGS((void));
  38. extern int Curdisp;
  39. extern struct proc *Display;
  40. FILE *Rawterm;
  41. volatile int Tick;
  42. int32 Clock;
  43. chtype MY_NORMAL;
  44. char Hashtab[256];
  45. extern char Eol[];
  46. extern int _gs_size(), _gs_gfd(), _gs_opt(), spawnvp();
  47. extern void _ss_opt(), clreol(), clrscr();
  48.  
  49. extern int Tracesession;
  50. extern char **environ;
  51. extern struct session *ScreenOwner;        /* Session currently displayed */
  52. extern struct session *Trace;
  53. extern int SYSback, SYSfore;
  54. extern TERMINAL *curses_in;
  55.  
  56. int Watchdog = 0;            /* Watch Dog off by default */
  57. int WDTick = 300*(1000 / MSPTICK);    /* 5 minutes watchdog timer */
  58. int WDCurr = 300*(1000 / MSPTICK);    /* Initial count down timer */
  59. short UseCurses = 0;
  60. int FIX1, FIX2;
  61.  
  62. static char Ttbuf[BUFSIZ];
  63. static char Tsbuf[BUFSIZ];
  64.  
  65. /* Keyboard input buffer */
  66. #define    KBSIZE    256
  67. static struct {
  68.     int buf[KBSIZE];
  69.     int *wp;
  70.     int *rp;
  71.     int cnt;
  72. } Keyboard;
  73.  
  74. int
  75. errhandler(errval,ax,bp,si)
  76. int errval,ax,bp,si;
  77. {
  78.     return 3;    /* Fail the system call */
  79. }
  80.  
  81. struct sgbuf svbuf;
  82.  
  83. /* Called at startup time to set up console I/O, memory heap */
  84. void
  85. ioinit()
  86. {
  87. struct sgbuf sbuf;
  88.  
  89.     setbuf(stdout,Tsbuf);
  90.  
  91.     Rawterm = fdopen (dup(1), "w");
  92.     setbuf(Rawterm,Ttbuf);
  93.     if (UseCurses)    {
  94.         initscr();
  95.         if (has_colors ())
  96.             MY_NORMAL = (COLOR_BLACK <<20) + (COLOR_BLUE <<16);
  97.         else
  98.             MY_NORMAL = A_NORMAL;
  99.         keypad (stdscr, 1);
  100.     }
  101.         _gs_opt(0, &sbuf);
  102.         _gs_opt(0, &svbuf);
  103.         sbuf.sg_case = 0;
  104.         sbuf.sg_backsp = 0;
  105.         sbuf.sg_delete = 0;
  106.         sbuf.sg_echo = 0;
  107. /*        sbuf.sg_alf = 0;    */
  108.         sbuf.sg_nulls = 0;
  109.         sbuf.sg_pause = 0;
  110.         sbuf.sg_page = 0;
  111.         sbuf.sg_bspch = 0;
  112.         sbuf.sg_dlnch = 0;
  113.         sbuf.sg_eorch = 0;
  114.         sbuf.sg_eofch = 0;
  115.         sbuf.sg_rlnch = 0;
  116.         sbuf.sg_dulnch = 0;
  117.         sbuf.sg_psch = 0;
  118. /*      sbuf.sg_kbich = 0;
  119.         sbuf.sg_kbach = 0;    */
  120.         sbuf.sg_bsech = 0;
  121.         sbuf.sg_bellch = 0;
  122. /*      sbuf.sg_xon = 0;
  123.         sbuf.sg_xoff = 0;
  124.         sbuf.sg_tabcr = 0;
  125.         sbuf.sg_tabsiz = 0;    */
  126.         _ss_opt(0, &sbuf);
  127.  
  128.     /* Initialize keyboard queue */
  129.     Keyboard.rp = Keyboard.wp = Keyboard.buf;
  130.  
  131. }
  132. /* Called just before exiting to restore console state */
  133. void
  134. iostop()
  135. {
  136.     struct iface *ifp,*iftmp;
  137.     void (**fp)();
  138.  
  139.         _ss_opt(0, &svbuf);
  140.     for(ifp = Ifaces;ifp != NULLIF;ifp = iftmp){
  141.         iftmp = ifp->next;
  142.         if_detach(ifp);
  143.     }
  144.     /* Call list of shutdown functions */
  145.     for(fp = Shutdown;*fp != NULLVFP;fp++)
  146.         (**fp)();
  147.     if (UseCurses)    {
  148.         wattrset (stdscr,MY_NORMAL);
  149.         clear ();
  150.         wrefresh (stdscr);
  151.         endwin();
  152.         UseCurses = 0;
  153.     }
  154. }
  155. #ifdef SHELL
  156. /* Spawn subshell */
  157. int
  158. doshell(argc,argv,p)
  159. int argc;
  160. char *argv[];
  161. void *p;
  162. {
  163. char *command;
  164. int ret;
  165. char *myargv[3];
  166.  
  167.     if(argc == 1) {
  168.         if((command = getenv("SHELL")) == NULLCHAR)
  169.             command = "SHELL";
  170.         puts ("Type 'LOGOUT' (or press <ESC>) to return to TNOS");
  171.         myargv[0] = command;
  172.         myargv[1] = "-p=\"\lTNOS-OS9: \"";
  173.         myargv[2] = (char *) 0;
  174.          ret = spawnvp(P_WAIT,command,myargv);
  175.     } else 
  176.         ret = spawnvp(P_WAIT,argv[1],(argv + 1));
  177.     return ret;
  178. }
  179. #endif
  180.  
  181. #ifdef ALLCMD
  182. /* Spawn mailer as subshell */
  183. int
  184. dobmail(argc,argv,p)
  185. int argc;
  186. char *argv[];
  187. void *p;
  188. {
  189.     char *command;
  190.     int ret;
  191.  
  192.     if((command = getenv("MAILER")) == NULLCHAR)
  193.         command = "BM";
  194.     ret = spawnvp(P_WAIT,command,argv);
  195.  
  196.     smtptick(NULL);        /* tickle smtp to send any mail */
  197.     return ret;
  198. }
  199. #endif /*ALLCMD*/
  200.  
  201. /* if watch-dog mode is set - make NOS reboot the system if it stalls */
  202. dowatchdog(argc,argv,p)
  203. int argc;
  204. char *argv[];
  205. void *p;
  206. {
  207.     return setbool(&Watchdog,"TNOS Watch Dog",argc,argv);
  208. }
  209.  
  210. /* Keyboard interrupt handler */
  211. void
  212. kbint()
  213. {
  214. int sig = 0;
  215. int c;
  216.  
  217.     while((c = kbraw()) != -1 && Keyboard.cnt < KBSIZE){
  218.         sig = 1;
  219.         *Keyboard.wp++ = c;
  220.         if(Keyboard.wp == &Keyboard.buf[KBSIZE])
  221.             Keyboard.wp = Keyboard.buf;
  222.         Keyboard.cnt++;
  223. #ifdef SCREENSAVER
  224.         sskick();
  225. #endif
  226.     }
  227.     if(sig){
  228.         psignal(&Keyboard,0);
  229.     }
  230. }
  231.  
  232. static int
  233. kbchar()
  234. {
  235. int c;
  236.  
  237.     while(Keyboard.cnt == 0)
  238.         pwait(&Keyboard);
  239.     Keyboard.cnt--;
  240.     c = *Keyboard.rp++;
  241.     if(Keyboard.rp == &Keyboard.buf[KBSIZE])
  242.         Keyboard.rp = Keyboard.buf;
  243.     return (c);
  244. }
  245. /* Flush the raw terminal output */
  246. void
  247. rflush()
  248. {
  249.     if (!UseCurses)
  250.         fflush(Rawterm);
  251.     else    {
  252. #ifdef SCREENSAVER
  253.         if (!ssenabled())    {
  254. #endif
  255.             if (ScreenOwner->split)
  256.                 wrefresh (ScreenOwner->screen->splitwin);
  257. /*            leaveok (ScreenOwner->screen->textwin, 0);    */
  258.             wrefresh (ScreenOwner->screen->textwin);
  259.             if (ScreenOwner->screen->statline)
  260.                 wrefresh (ScreenOwner->screen->statwin);
  261. #ifdef SCREENSAVER
  262.         }
  263. #endif
  264.     }
  265. }
  266.  
  267. #ifdef ALLCMD
  268. struct funcstr {
  269.     short fkey;
  270.     char alloced;
  271.     char *fvalue;
  272. };
  273.  
  274. struct funcstr fkeys[] = {
  275.     KEY_BTAB,0,NULLCHAR,        /* tab + shift */
  276.     KEY_F1,1,NULLCHAR,          /* F1 */
  277.     KEY_F2,1,NULLCHAR,          /* F2 */
  278.     KEY_F3,1,NULLCHAR,          /* F3 */
  279.     KEY_F4,1,NULLCHAR,          /* F4 */
  280.     KEY_F5,0,NULLCHAR,        /* F5 */
  281.     KEY_F6,0,NULLCHAR,        /* F6 */
  282.     KEY_F7,0,NULLCHAR,        /* F7 */
  283.     KEY_F8,0,NULLCHAR,        /* F8 */
  284.     KEY_F9,0,NULLCHAR,        /* F9 */
  285.     KEY_F10,0,NULLCHAR,        /* F10 */
  286.     KEY_HOME,1,NULLCHAR,        /* home*/
  287.     KEY_UP,1,"\033[A",        /* up arrow*/
  288.     KEY_PPAGE,1,NULLCHAR,        /* pgup */
  289.     KEY_LEFT,1,"\033[D",        /* left arrow */
  290.     KEY_RIGHT,1,"\033[C",        /* right arrow */
  291.     KEY_END,1,NULLCHAR,        /* end */
  292.     KEY_DOWN,1,"\033[B",        /* down arrow */
  293.     KEY_NPAGE,1,NULLCHAR,        /* pgdn */
  294.     KEY_IC,1,NULLCHAR,        /* ins */
  295.     KEY_DC,1,NULLCHAR,        /* del */
  296.     KEY_SF1,0,NULLCHAR,        /* F1 + shift*/
  297.     KEY_SF2,0,NULLCHAR,        /* F2 + shift*/
  298.     KEY_SF3,0,NULLCHAR,        /* F3 + shift*/
  299.     KEY_SF4,0,NULLCHAR,        /* F4 + shift*/
  300.     KEY_SF5,0,NULLCHAR,        /* F5 + shift*/
  301.     KEY_SF6,0,NULLCHAR,        /* F6 + shift*/
  302.     KEY_SF7,0,NULLCHAR,        /* F7 + shift*/
  303.     KEY_SF8,0,NULLCHAR,        /* F8 + shift*/
  304.     KEY_SF9,0,NULLCHAR,        /* F9 + shift*/
  305.     KEY_SF10,0,NULLCHAR,        /* F10 + shift*/
  306.     KEY_CTL_F1,0,NULLCHAR,        /* F1 + control*/
  307.     KEY_CTL_F2,0,NULLCHAR,        /* F2 + control*/
  308.     KEY_CTL_F3,0,NULLCHAR,        /* F3 + control*/
  309.     KEY_CTL_F4,0,NULLCHAR,        /* F4 + control*/
  310.     KEY_CTL_F5,0,NULLCHAR,        /* F5 + control*/
  311.     KEY_CTL_F6,0,NULLCHAR,        /* F6 + control*/
  312.     KEY_CTL_F7,0,NULLCHAR,        /* F7 + control*/
  313.     KEY_CTL_F8,0,NULLCHAR,        /* F8 + control*/
  314.     KEY_CTL_F9,0,NULLCHAR,        /* F9 + control*/
  315.     KEY_CTL_F10,0,NULLCHAR,        /* F10 + control*/
  316.     KEY_ALTKBD+KEY_F1,0,NULLCHAR,    /* F1 + alt*/
  317.     KEY_ALTKBD+KEY_F2,0,NULLCHAR,    /* F2 + alt*/
  318.     KEY_ALTKBD+KEY_F3,0,NULLCHAR,    /* F3 + alt*/
  319.     KEY_ALTKBD+KEY_F4,0,NULLCHAR,    /* F4 + alt*/
  320.     KEY_ALTKBD+KEY_F5,0,NULLCHAR,    /* F5 + alt*/
  321.     KEY_ALTKBD+KEY_F6,0,NULLCHAR,    /* F6 + alt*/
  322.     KEY_ALTKBD+KEY_F7,0,NULLCHAR,    /* F7 + alt*/
  323.     KEY_ALTKBD+KEY_F8,0,NULLCHAR,    /* F8 + alt*/
  324.     KEY_ALTKBD+KEY_F9,0,NULLCHAR,    /* F9 + alt*/
  325.     KEY_ALTKBD+KEY_F10,0,NULLCHAR,    /* F10 + alt*/
  326.     KEY_SEND,0,NULLCHAR,        /* end  + ctl */
  327.     KEY_SR,0,NULLCHAR,        /* pgup + ctl */
  328.     KEY_SHOME,0,NULLCHAR,        /* home + ctl */
  329.     KEY_SF,0,NULLCHAR,        /* pgdn + ctl */
  330.       0,0,NULLCHAR
  331. };
  332.  
  333. char Leftover = 0;
  334. char *Nextkey;
  335. #endif /*ALLCMD*/
  336.  
  337. /* Read characters from the keyboard, translating them to "real" ASCII.
  338.  * If none are ready, block. The F-10 key is special; translate it to -2.
  339.  */
  340. #ifdef ALLCMD
  341. int
  342. kbread()
  343. {
  344. int c,i,j;
  345.  
  346.     if((c = Leftover) != 0)  {
  347.         Leftover = *Nextkey++;
  348.         return c;
  349.     }
  350.     c = kbchar();
  351.     if (c < 256)
  352.         return (c);
  353.     switch (c)    {
  354.         case KEY_UP:    /* UP ARROW key (used as previous history command) */
  355.             if(Current == Command) {   
  356.                 c = UPARROW;
  357.                 break;
  358.             }
  359.             goto all;
  360.         case KEY_DOWN:    /* DOWN ARROW key (used as next history command) */
  361.             if(Current == Command) {
  362.                 c = DNARROW;
  363.                 break;
  364.             }
  365.             goto all;
  366.             case KEY_F10:    /* F-10 key (used as command-mode escape) */
  367.             if(fkeys[10].fvalue == NULLCHAR){
  368.                 c = -2;
  369.                 break;
  370.             }
  371.                 goto all;
  372.             case KEY_IC:   /* INSERT key (used as status line toggle) */
  373.             if(fkeys[19].fvalue == NULLCHAR){
  374.                 c = -105;
  375.                 break;
  376.             }
  377.             goto all;
  378.             case KEY_DC:   /* DELETE key (used as flow mode toggle) */
  379.             if(fkeys[20].fvalue == NULLCHAR){
  380.                 c = -106;
  381.                 break;
  382.             }
  383.             goto all;
  384.             case KEY_HOME:   /* HOME key (used to kick this session) */
  385.             if(fkeys[11].fvalue == NULLCHAR){
  386.                 c = -107;
  387.                 break;
  388.             }
  389.             goto all;
  390.             case KEY_END:   /* END key (used to kill this session) */
  391.             if(fkeys[16].fvalue == NULLCHAR){
  392.                 c = -108;
  393.                 break;
  394.             }
  395.             goto all;
  396.             case KEY_PPAGE:   /* PGUP key (used to toggle to previous session) */
  397.             if(fkeys[13].fvalue == NULLCHAR){
  398.                 c = -109;
  399.                 break;
  400.             }
  401.             goto all;
  402.             case KEY_NPAGE:   /* PGDN key (used to toggle to next session) */
  403.             if(fkeys[18].fvalue == NULLCHAR){
  404.                 c = -110;
  405.                 break;
  406.             }
  407.             goto all;
  408. #ifdef notyet
  409.         case KEY_BACKSPACE:
  410.             c = '\b';
  411.             goto all;
  412.         case KEY_ENTER:
  413.             c = '\n';
  414.             goto all;
  415. #endif
  416.             default:    /* Dunno what it is */
  417. all:
  418.             if(c > KEY_F0 && c < KEY_F10) {  /* F1 to F9 */
  419.                 if(fkeys[c-KEY_F1+1].fvalue == NULLCHAR) {
  420.                     c = ((c - KEY_F1) + 3) * -1; /* NO fkey defined - WG7J */
  421.                     break;
  422.                 }
  423.             }
  424.             for(i=0;(j = fkeys[i].fkey) != 0;i++)
  425.                 if(j == c) {
  426.                     Nextkey = fkeys[i].fvalue;
  427.                     if(Nextkey == NULLCHAR) {
  428.                         c = -1;
  429.                         return c;
  430.                     }
  431.                     /* If first char of fvalue is '~'
  432.                      * switch to command session.
  433.                      */
  434.                     if((c = *Nextkey++) == '~') {
  435.                         c = -2;
  436.                         Leftover = *Nextkey++;
  437.                     } else {
  438.                         if(c != 0)
  439.                             Leftover = *Nextkey++;
  440.                         else
  441.                             c = -1;
  442.                     }
  443.                     return c;
  444.                 }
  445.             c = -1;
  446.         }
  447.     return c;
  448. }
  449. #else /*ALLCMD*/
  450.  
  451. int
  452. kbread()
  453. {
  454. int c;
  455.  
  456.     c = kbchar();
  457.     if(Current == Command) {    /* Check for command recall */
  458.         if(c == KEY_UP)     /* UP arrow */
  459.             return UPARROW;
  460.         if(c == KEY_DOWN)     /* DOWN arrow */
  461.             return DNARROW;
  462.     }
  463.     if (c < 256)
  464.         return (c);
  465.     switch(c)    {
  466.         case KEY_F10:        /* F-10 key (used as command-mode escape) */
  467.             c = -2;
  468.             break;
  469.         case KEY_DL:        /* DEL key */
  470.             c = 0x7f;
  471.             break;
  472.         case KEY_BACKSPACE:
  473.             c = '\b';
  474.             break;
  475.         case KEY_ENTER:
  476.             c = '\n';
  477.             break;
  478.         default:        /* Dunno what it is */
  479.             if(c > KEY_F0 && c < KEY_F10)    /* F1 to F9 */
  480.                 c = ((c - KEY_F1) + 3) * -1;
  481.             else
  482.                 c = -1;
  483.     }
  484.         return c;
  485. }
  486.  
  487. #endif /*ALLCMD*/
  488.  
  489. #ifdef ALLCMD
  490. int
  491. dofkey(argc,argv,p)
  492. int argc;
  493. char *argv[];
  494. void *p;
  495. {
  496. int c,i,j;
  497. char *q, *r;
  498. char str[100];
  499.  
  500.     if(argc == 1) {
  501.        tprintf("     key   num    key    num    key    num    key    num   key    num\n");
  502.        tprintf("     f1    265    sf1    281    cf1    297    af1    393   pgup   339\n");
  503.        tprintf("     f2    266    sf2    282    cf2    298    af2    394   pgdn   338\n");
  504.        tprintf("     f3    267    sf3    283    cf3    299    af3    395   home   262\n");
  505.        tprintf("     f4    268    sf4    284    cf4    300    af4    396   end    360\n");
  506.        tprintf("     f5    269    sf5    285    cf5    301    af5    397   arup   259\n");
  507.        tprintf("     f6    270    sf6    286    cf6    302    af6    398   ardn   258\n");
  508.        tprintf("     f7    271    sf7    287    cf7    303    af7    399   ar l   260\n");
  509.        tprintf("     f8    272    sf8    288    cf8    304    af8    400   ar r   261\n");
  510.        tprintf("     f9    273    sf9    289    cf9    305    af9    401   ins    331\n");
  511.        tprintf("     f10   274    sf10   290    cf10   306    af10   402   del    330\n");
  512.        tprintf("     cpgup 337    cpgdn  336    chome  391    cend   386   stab   353\n\n");
  513.        tprintf("usage: fkey <key number> [<value> | \"string\"]\n");
  514.        return 0;
  515.     }
  516.  
  517.     c = atoi(argv[1]);
  518.     if(c < KEY_BREAK || c > KEY_SF20+KEY_ALTKBD) {
  519.         tprintf("fkey number out of range.\n");
  520.         return 1;
  521.     }
  522.  
  523.     for(j = 0;(i = fkeys[j].fkey) != 0; j++)
  524.         if(i == c) 
  525.             break;
  526.  
  527.     if(i == 0){
  528.         tprintf("fkey number not found\n");
  529.         return 1;
  530.     }
  531.  
  532.     if(argc == 2) {
  533.         q = fkeys[j].fvalue;
  534.         r = str;
  535.         if(q == NULLCHAR)
  536.             tprintf("fkey %d has no assigned value.\n",c);
  537.         else {
  538.             while(*q)
  539.                 if(*q < ' ') { /* This is ASCII dependent !! */
  540.                     *r++ = '^';
  541.                     *r++ = *q++ + 0x40;
  542.                 } else
  543.                     *r++ = *q++;
  544.             *r = '\0';
  545.             tprintf("fkey = %s\n",str);
  546.         }
  547.         return 0;
  548.     }
  549.  
  550.     if(argc == 3) {
  551.         if(fkeys[j].alloced)
  552.             fkeys[j].alloced = 0;
  553.         else
  554.             if(fkeys[j].fvalue != NULLCHAR)
  555.                 free(fkeys[j].fvalue);
  556.  
  557.         r = str;
  558.         q = argv[2];
  559.         while(*q){
  560.             if(*q == '^'){    /* ^ gives control char next */
  561.                 q++;
  562.                 if(*q == '^') {
  563.                     *r++ = *q++; /* No, he wants a ^ */
  564.                 } else {
  565.                     *r++ = *q++ & 0x1f;
  566.                 }
  567.             } else
  568.                 *r++ = *q++;
  569.         }
  570.         *r = '\0';
  571.         fkeys[j].fvalue = strdup(str);
  572.     }
  573.     return 0;
  574. }
  575. #endif /*ALLCMD*/
  576.  
  577. /* Called on each NOS clock tick. Signal a clock tick to the timer process.
  578.  */
  579. void
  580. ctick()
  581. {
  582.     if(Watchdog)
  583.         if(WDCurr-- == 0)
  584.             sysreset();    
  585.     Tick++;
  586.     psignal(&Tick,1);
  587. }
  588. /* Called from the timer process on every tick. NOTE! This function
  589.  * can NOT be called at interrupt time because it calls the BIOS
  590.  */
  591. void
  592. pctick()
  593. {
  594.     Clock = clock() / 2;
  595. }
  596.  
  597. /* Convert a pointer to a long integer */
  598. long
  599. ptol(p)
  600. void *p;
  601. {
  602.     return ((long) p);
  603. }
  604.  
  605. void *
  606. ltop(l)
  607. long l;
  608. {
  609.     return (l);
  610. }
  611.  
  612.  
  613. void
  614. sysreset()
  615. {
  616. #asm
  617.     move.l    0,a7
  618.     move.l    4,a0
  619.     jmp     (a0)
  620. #endasm
  621. }
  622.  
  623. extern unsigned char SCREENwidth, SCREENlength;
  624. extern int STATLINE;
  625.  
  626. void
  627. newscreen(sp)
  628. struct session *sp;
  629. {
  630. struct session *old;
  631.  
  632.     if(sp != NULLSESSION)    {
  633.         sp->screen = callocw(1,sizeof(struct screen));
  634.         sp->screen->statline = STATLINE;
  635.         sp->screen->attr = MY_NORMAL >> 16;
  636.         if (UseCurses)        {
  637.             sp->screen->win = sp->screen->textwin = newwin (24 - (sp->split * 2), 80, 0, 0);
  638.             if (sp->split)    {
  639.                 sp->screen->splitwin = newwin (2, 80, 22, 0);
  640.                 leaveok (sp->screen->splitwin, 1);
  641.                 if (!has_colors())
  642.                     wattrset (sp->screen->splitwin, A_REVERSE);
  643.                 else
  644.                     wattrset (sp->screen->splitwin, (SYSback >> 4)+(SYSfore << 4));
  645.                 werase (sp->screen->splitwin);
  646.                 waddch (sp->screen->splitwin, '_');
  647.                 wmove (sp->screen->splitwin, 0, 0);
  648.             }
  649.             scrollok (sp->screen->win, 1);
  650.             if (has_colors())
  651.                 sp->screen->attr = (SYSback+SYSfore) >> 16;
  652.             wattrset (sp->screen->win, sp->screen->attr << 16);
  653.             wclear (sp->screen->win);
  654.         }
  655.     }
  656. }
  657. void
  658. freescreen(sp)
  659. struct session *sp;
  660. {
  661.     if(sp == NULLSESSION || sp->screen == NULLSCREEN)
  662.         return;
  663.     if (UseCurses)    {
  664.         delwin (sp->screen->textwin);
  665.         if (sp->split)
  666.             delwin (sp->screen->splitwin);
  667.         if (sp->screen->statline)
  668.             delwin (sp->screen->statwin);
  669.     }
  670.     free((char *)sp->screen);
  671. }
  672.  
  673.  
  674. /* Save specified session screen and resume console screen */
  675. void
  676. swapscreen(old,new)
  677. struct session *old,*new;
  678. {
  679.     if (old != NULLSESSION && UseCurses)
  680.         rflush ();
  681.     ScreenOwner = new;
  682.     if (new != NULLSESSION && UseCurses)        {
  683.         touchwin (new->screen->textwin);
  684.         if (new->split)
  685.             touchwin (new->screen->splitwin);
  686.         if (new->screen->statwin)
  687.             touchwin (new->screen->statwin);
  688.         displayStatLine (0, 1);
  689.         rflush ();
  690.     }
  691.     alert(Display,1);    /* Wake him up */
  692. }
  693.  
  694. void
  695. display(i,v1,v2)
  696. int i;
  697. void *v1;
  698. void *v2;
  699. {
  700.     int c;
  701.     struct session *sp;
  702.  
  703.     /* This is very tricky code. Because the value of "Current" can
  704.      * change any time we do a pwait, we have to be careful to detect
  705.      * any change and go back and start again.
  706.      */
  707.     for(;;){
  708.         sp = Current;
  709.  
  710.         if(sp->morewait){
  711.             pwait(&sp->row);
  712.             if(sp != Current || sp->row <= 0){
  713.                 /* Current changed value, or the user
  714.                  * hasn't really hit a key
  715.                  */
  716.                 continue;
  717.             }
  718.             /* Erase the prompt */
  719.             if (UseCurses)    {
  720. #ifdef SCREENSAVER
  721.                 sskick();
  722. #endif
  723.                 waddstr(ScreenOwner->screen->win,"\b\b\b\b\b\b\b\b        \b\b\b\b\b\b\b\b");
  724.             } else
  725.                 fprintf(Rawterm,"\b\b\b\b\b\b\b\b        \b\b\b\b\b\b\b\b");
  726.             rflush();
  727.         }
  728.         sp->morewait = 0;
  729.         if((c = rrecvchar(sp->output)) == -1){
  730.             /* the alert() in swapscreen will cause this to
  731.              * return -1 when current changes
  732.              */
  733.             pwait(NULL);    /* Prevent a nasty loop */
  734.             continue;
  735.         }
  736. #ifdef SCREENSAVER
  737.         sskick ();
  738. #endif
  739.         if (c == '\l')
  740.             continue;
  741.         if(c == '\n'){
  742.             cputs(Eol);
  743. /*            clreol();    */
  744.         } else
  745.             putch(c);
  746.         /* Fix by Ron Murray, vk6zjm */
  747.         if(sp->record != NULLFILE)      /* Don't save CR if ascii mode */
  748.             if (c != '\l' || sockmode(sp->output, -1) != SOCK_ASCII)
  749.                 putc(c,sp->record);
  750.         if(sp->flowmode && c == '\n' && --sp->row <= 0){
  751.             if (!UseCurses)
  752.             fprintf(Rawterm,"--More--");
  753.         else    {
  754. #ifdef SCREENSAVER
  755.             sskick();
  756. #endif
  757.             waddstr(ScreenOwner->screen->win,"--More--");
  758.         }
  759.         sp->morewait = 1;
  760.         }
  761.     }
  762. }
  763. /* Return time since startup in milliseconds. */
  764. int32
  765. msclock()
  766. {
  767.     return Clock * MSPTICK;
  768. }
  769. /* Return clock in seconds */
  770. int32
  771. secclock()
  772. {
  773.     return Clock * MSPTICK / 1000L;
  774. }
  775.  
  776. /* same as getenv(), but return "" instead of NULL when it does not exist */
  777. char *getnenv (name)
  778. char *name;
  779. {
  780.     char *rv;
  781.  
  782.     if ((rv = getenv(name)) == NULL)
  783.          rv = "";            /* NULL replaced by "" */
  784.  
  785.     return rv;
  786. }
  787.  
  788. int TNOS_68KAlarm;
  789.  
  790. int
  791. housekeeping (sig)
  792. int sig;
  793. {
  794.     switch (sig)    {
  795.         case 3:        if (UseCurses)    {
  796.                     endwin();
  797.                     UseCurses = 0;
  798.                     clrscr();
  799.                 }
  800.                 _ss_opt(0, &svbuf);    
  801.                 exit (0);
  802.                 break;
  803.         case 6809:    ctick();
  804.         default:    break;
  805.     }
  806. }
  807.  
  808.  
  809. void
  810. oskinit()
  811. {
  812.     intercept (housekeeping);
  813.     TNOS_68KAlarm = alm_cycle (6809, 2);
  814. }
  815.  
  816.  
  817. _dos_getfileattr (file, attr)
  818. char *file;
  819. unsigned *attr;
  820. {
  821. FILE *fp;
  822. struct fildes b;
  823.  
  824.     if ((fp = fopen (file, "r")) == NULLFILE)
  825.         if ((fp = fopen (file, "d")) == NULLFILE)
  826.             return -1;
  827.     _gs_gfd (fileno(fp), &b, sizeof (struct fildes));
  828.     fclose (fp);
  829.     *attr = (b.fd_att & 0x80) ? FA_DIREC : 0;
  830.     return 0;
  831. }
  832.  
  833. int
  834. putch (c)
  835. int c;
  836. {
  837. static short lastwasCR = 0;
  838.     
  839.     if (c == '\l' && !lastwasCR)    {
  840.         FIX1++;
  841.         c = '\n';
  842.     }
  843.     lastwasCR = (c == '\n') ? 1 : 0;
  844.     if (!UseCurses)    {
  845.         if (c != '\l')
  846.             putchar (c);
  847.         return 0;
  848.     }
  849.     if (c == '\007')
  850.         beep ();
  851.     else    {
  852. #ifdef SCREENSAVER
  853.         sskick();
  854. #endif
  855.         waddch (ScreenOwner->screen->win, c);
  856.         if (c == '\n')    {
  857.             waddch (ScreenOwner->screen->win, '\l');
  858.             rflush ();
  859.         }
  860.     }
  861.     return 0;
  862. }
  863.  
  864. void
  865. highvideo ()
  866. {
  867. int back, fore;
  868.  
  869.     if (UseCurses && has_colors())    {
  870. #ifdef SCREENSAVER
  871.         sskick();
  872. #endif
  873.         fore = (ScreenOwner->screen->attr & 0x0f);
  874.         fore = (fore) ? fore - 1 : 7;
  875.         fore <<= 16;
  876.         back = (ScreenOwner->screen->attr & 0xf0) << 16;
  877.         wattrset (ScreenOwner->screen->win, back+fore);
  878.     }
  879. }
  880.  
  881. void
  882. lowvideo()
  883. {
  884. int back, fore;
  885.  
  886.     if (UseCurses && has_colors())    {
  887. #ifdef SCREENSAVER
  888.         sskick();
  889. #endif
  890.         wattrset (ScreenOwner->screen->win, ScreenOwner->screen->attr << 16);
  891.     }
  892. }
  893.  
  894. int
  895. cputs (str)
  896. char *str;
  897. {
  898.     while (*str)
  899.         putch (*str++);
  900.     return 0;
  901. }
  902.  
  903. void
  904. clreol ()
  905. {
  906.     if (UseCurses)    {
  907. #ifdef SCREENSAVER
  908.         sskick ();
  909. #endif
  910.         wclrtoeol (ScreenOwner->screen->win);
  911.     }
  912. }
  913.  
  914. void
  915. clrscr ()
  916. {
  917. int k;
  918.  
  919.     if (UseCurses)    {
  920. #ifdef SCREENSAVER
  921.         sskick();
  922. #endif
  923.         werase (ScreenOwner->screen->win);
  924.         wrefresh (ScreenOwner->screen->win);
  925.     } else    {
  926.         for (k = 0; k < 24; k++)
  927.             putchar ('\n');
  928.     }
  929. }
  930.  
  931. int
  932. wherey ()
  933. {
  934. int y = 0, x;
  935.  
  936.     if (UseCurses)    {
  937. #ifdef SCREENSAVER
  938.         sskick();
  939. #endif
  940.         getyx (ScreenOwner->screen->win, y, x);
  941.     }
  942.     return y;
  943. }
  944.  
  945. int
  946. wherex ()
  947. {
  948. int y, x = 0;
  949.  
  950.     if (UseCurses)    {
  951. #ifdef SCREENSAVER
  952.         sskick();
  953. #endif
  954.         getyx (ScreenOwner->screen->win, y, x);
  955.     }
  956.     return x;
  957. }
  958.  
  959. void
  960. gotoxy (x, y)
  961. int x, y;
  962. {
  963.     if (UseCurses)    {
  964. #ifdef SCREENSAVER
  965.         sskick();
  966. #endif
  967.         wmove (ScreenOwner->screen->win, y, x);
  968.     }
  969. }
  970.  
  971. void
  972. hardretn (i)
  973. int i;
  974. {
  975. }
  976.  
  977. unsigned long
  978. farcoreleft ()
  979. {
  980.     return (coreleft());
  981. }
  982.  
  983. int
  984. fputc (c, fp)
  985. int c;
  986. FILE *fp;
  987. {
  988.     return (putc (c, fp));
  989. }
  990.  
  991. void
  992. getdate (datep)
  993. struct date *datep;
  994. {
  995. int time, date, tick;
  996. short day, *sp;
  997. char *cp;
  998.  
  999.     _sysdate (0, &time, &date, &day, &tick);
  1000.     sp = (short *) &date;
  1001.     datep->da_year = *sp++;
  1002.     cp = (char *) sp;
  1003.     datep->da_mon = *cp++;
  1004.     datep->da_day = *cp;
  1005. }
  1006.  
  1007. void
  1008. gettime (timep)
  1009. struct time *timep;
  1010. {
  1011. int time, date, tick;
  1012. short day;
  1013. char *cp;
  1014.  
  1015.     _sysdate (0, &time, &date, &day, &tick);
  1016.     cp = (char *) &time;
  1017.     cp++;
  1018.     timep->ti_hour = *cp++;
  1019.     timep->ti_min = *cp++;
  1020.     timep->ti_sec = *cp;
  1021.     cp = (char *) &tick;
  1022.     cp += 3;
  1023.     timep->ti_hund = *cp;
  1024. }
  1025.  
  1026. int dirps ()
  1027. {
  1028. }
  1029.  
  1030. void restore (c)
  1031. char c;
  1032. {
  1033. }
  1034.  
  1035. int istate()
  1036. {
  1037.     return (1);
  1038. }
  1039.  
  1040. int
  1041. spawnvp (mode,path,argv)
  1042. int mode;
  1043. char *path, *argv[];
  1044. {
  1045. int retval, status, w;
  1046. struct sgbuf sbuf;
  1047.  
  1048.         _gs_opt(0, &sbuf);
  1049.         _ss_opt(0, &svbuf);
  1050.     if (UseCurses)
  1051.         endwin();
  1052.     retval = os9exec(os9forkc, path, argv, environ, 0, 0, 3);
  1053.         if (retval)
  1054.         while ((w = wait(&status)) != retval && w != -1)
  1055.             ;
  1056.         _ss_opt(0, &sbuf);
  1057.         if (UseCurses)    {
  1058. #ifdef SCREENSAVER
  1059.             sskick();
  1060. #endif
  1061.             touchwin (ScreenOwner->screen->win);
  1062.             wrefresh (ScreenOwner->screen->win);
  1063.         }
  1064.     return (retval);
  1065. }
  1066.  
  1067. int
  1068. getcbrk()
  1069. {
  1070.     return 0;
  1071. }
  1072.  
  1073. int
  1074. setcbrk(mode)
  1075. int mode;
  1076. {
  1077.     return mode;
  1078. }
  1079.  
  1080.  
  1081. void
  1082. giveup()
  1083. {
  1084. }
  1085.  
  1086. wready ()
  1087. {
  1088. int stat;
  1089.  
  1090.      stat = curses_in->buf_hi_water - curses_in->buf_lo_water;
  1091.      if (!stat)          {
  1092.           stat = _gs_rdy (fileno (stdin));
  1093.           stat = (stat > 0) ? 1 : 0;
  1094.           }
  1095.      return (stat);
  1096. }
  1097.  
  1098.  
  1099. kbraw()
  1100. {
  1101. unsigned char c;
  1102. int ci = -1;
  1103. static char sendaLF = 0;
  1104.  
  1105. #ifdef notagain
  1106.     if (sendaLF)    {
  1107.         sendaLF = 0;
  1108.         return '\l';
  1109.     }
  1110.     sendaLF = 0;
  1111. #endif
  1112.     if (UseCurses)    {
  1113.         if (wready ())
  1114.             ci = wgetch (stdscr);
  1115.         if (ci == KEY_ENTER)    {
  1116.             ci = '\n';
  1117.             sendaLF = 1;
  1118.         }
  1119.         if (ci == KEY_BACKSPACE)
  1120.             ci = '\b';
  1121.         return ci;
  1122.     } else    {
  1123.         if (_gs_rdy(0) < 0)
  1124.             return -1;
  1125.         read(0, &c, 1);
  1126.         if (c == '\n')
  1127.             sendaLF = 1;
  1128.         return c;
  1129.     }
  1130. }
  1131.  
  1132. int
  1133. FP_SEG (i)
  1134. int i;
  1135. {
  1136.     return i;
  1137. }
  1138.  
  1139. int
  1140. FP_OFF (i)
  1141. int i;
  1142. {
  1143.     return i;
  1144. }
  1145.  
  1146. void *
  1147. mallocw(nb)
  1148. unsigned nb;
  1149. {
  1150.     register void *p;
  1151.  
  1152.     while((p = malloc(nb)) == NULL){
  1153.         sleep (1);
  1154.     }
  1155.     return p;
  1156. }
  1157.  
  1158. void *
  1159. callocw(nelem,size)
  1160. unsigned nelem;    /* Number of elements */
  1161. unsigned size;    /* Size of each element */
  1162. {
  1163.     register unsigned i;
  1164.     register char *cp;
  1165.  
  1166.     i = nelem * size;
  1167.     cp = mallocw(i);
  1168.     memset(cp,0,i);
  1169.     return cp;
  1170. }
  1171.  
  1172. /* Return available memory on our heap plus available system memory */
  1173. unsigned long
  1174. availmem()
  1175. {
  1176.     return (coreleft());
  1177. }
  1178.  
  1179.  
  1180. char *
  1181. stpcpy (dest, src)
  1182. char *dest, *src;
  1183. {
  1184.     strcpy (dest, src);
  1185.     return (dest+strlen(src));
  1186. }
  1187.  
  1188.  
  1189. long
  1190. dostounix (d, t)
  1191. struct date *d;
  1192. struct time *t;
  1193. {
  1194.     return 1L;
  1195. }
  1196.  
  1197. int
  1198. stime (t)
  1199. time_t *t;
  1200. {
  1201.     return 0;
  1202. }
  1203.  
  1204.  
  1205. void
  1206. _strtime (str)
  1207. char *str;
  1208. {
  1209. char *cp;
  1210. int k;
  1211. time_t tm;
  1212.  
  1213.     time (&tm);
  1214.     cp = ctime (&tm);
  1215.     cp += 11;
  1216.     for (k = 0; k < 8; k++)
  1217.         *str++ = *cp++;
  1218.     *str = 0;
  1219. }
  1220.  
  1221. void
  1222. screendaemon (i,v1,v2)
  1223. int i;        /* Args not used */
  1224. char *v1;
  1225. void *v2;
  1226. {
  1227.     if (!UseCurses)
  1228.         return;
  1229.     for(;;){
  1230.         mspause(500L);    /* Run displayStatLine every 1/2 second */
  1231.         displayStatLine (0, 1);
  1232.         mspause(500L);    /* and run the rest every second */
  1233.         displayStatLine (0, 0);
  1234. #ifdef SCREENSAVER
  1235.         screensaver ();
  1236. #endif
  1237.     }
  1238. }
  1239.  
  1240. #define SOBUF 256
  1241.  
  1242. /* Printf to Trace session screen or file. Doesn't use ANSI vsprintf */
  1243. int
  1244. traceprintf(fp,fmt,arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10,arg11,arg12)
  1245. FILE *fp;        /* Trace file stream */
  1246. char *fmt;        /* Message format */
  1247. int arg1,arg2,arg3;    /* Arguments */
  1248. int arg4,arg5,arg6;
  1249. int arg7,arg8,arg9;
  1250. int arg10,arg11,arg12;
  1251. {
  1252. int len,withargs;
  1253. char *buf;
  1254.  
  1255.     if(strchr(fmt,'%') == NULLCHAR){
  1256.         /* No args, so we don't need vsprintf() */
  1257.         withargs = 0;
  1258.         buf = fmt;
  1259.         len = strlen(fmt);
  1260.     } else {
  1261.         /* Use a default value that is hopefully longer than the
  1262.          * biggest output string we'll ever print (!)
  1263.          */
  1264.         withargs = 1;
  1265.         buf = mallocw(SOBUF);
  1266.         if((len=sprintf(buf,fmt,arg1,arg2,arg3,arg4,arg5,arg6,arg7,
  1267.             arg8,arg9,arg10,arg11,arg12)) >= SOBUF) {
  1268.             /* It's too late to be sorry. He's dead, Jim. */
  1269.             log(-1,"traceprintf() has exceeded the size of it's buffer. Restarting TNOS.");
  1270.             where_outta_here(1);
  1271.         }
  1272.     }
  1273.     if (UseCurses && (Current == Trace) && (fp == stdout))
  1274.         cputs(buf);
  1275.     else
  1276.         fprintf (fp, buf);
  1277.  
  1278.     if(withargs)
  1279.         free(buf);
  1280.     return len;
  1281. }
  1282.  
  1283.  
  1284. int16 *
  1285. getstack()
  1286. {
  1287. #asm
  1288.     move.l    a7,d0
  1289.     addq.l    #4,d0
  1290. #endasm
  1291. }
  1292.  
  1293. #asm
  1294. setjmp:    move.l a0,-(a7)
  1295.     movea.l d0,a0
  1296.     move.l 4(a7),(a0)
  1297.     movem.l d0-d7,4(a0)
  1298.     movem.l a1-a7,40(a0)
  1299.     move.l (a7)+,36(a0)
  1300.     moveq.l #0,d0
  1301.     rts
  1302.  
  1303. longjmp:
  1304.     movea.l d0,a0
  1305.     movem.l 4(a0),d0-d7
  1306.     movem.l 40(a0),a1-a7
  1307.     movea.l (a0),a0
  1308.     pea.l (a0)
  1309.     movea.l 36(a0),a0
  1310.     rts
  1311. #endasm
  1312.  
  1313.